<template>
  <div class="tabs-container">
    <el-scrollbar class="scroll-container" ref="scrollContainer">
      <div class="tabs-nav">
        <div
          v-for="tag in visitedViews"
          :key="tag.path"
          :class="['button-tab', isActive(tag) ? 'active' : '']"
          @click="handleClick(tag)">
          {{ tag.title }}
          <i v-if="!tag.meta.affix" class="el-icon-close" @click.stop="closeSelectedTag(tag)"></i>
        </div>
      </div>
    </el-scrollbar>
    <div class="tabs-actions">
      <el-dropdown trigger="click" @command="handleCommand">
        <span class="tabs-action-button">
          <i class="el-icon-arrow-down"></i>
        </span>
        <template #dropdown>
          <el-dropdown-menu>
            <el-dropdown-item command="closeOthers">关闭其他</el-dropdown-item>
            <el-dropdown-item command="closeAll">关闭所有</el-dropdown-item>
          </el-dropdown-menu>
        </template>
      </el-dropdown>
    </div>
  </div>
</template>

<script>
/**
 * 模拟path.resolve功能的简单方法
 */
function pathResolve(basePath, routePath) {
  if (basePath !== '/' && basePath.endsWith('/')) {
    basePath = basePath.slice(0, -1)
  }
  
  if (routePath.startsWith('/')) {
    return routePath
  }
  
  return `${basePath}/${routePath}`
}

export default {
  name: 'TabsNav',
  computed: {
    visitedViews() {
      return this.$store.getters.visitedViews || []
    }
  },
  watch: {
    $route() {
      this.addViewTabs()
    }
  },
  mounted() {
    this.initTags()
    this.addViewTabs()
  },
  methods: {
    /**
     * 判断路由是否激活
     */
    isActive(route) {
      return route.path === this.$route.path
    },
    
    /**
     * 初始化标签，处理从localStorage恢复的标签
     */
    initTags() {
      const routes = this.$store.getters.routes || []
      
      const affixTags = this.filterAffixTags(routes)
      
      if (affixTags && affixTags.length) {
        for (const tag of affixTags) {
          if (tag.name && !this.visitedViews.some(v => v.path === tag.path)) {
            this.$store.dispatch('tagsView/addVisitedView', tag)
          }
        }
      }

      const currentRoute = this.$route
      if (currentRoute.name && !this.visitedViews.some(v => v.path === currentRoute.path)) {
        this.$store.dispatch('tagsView/addVisitedView', currentRoute)
      }
    },
    
    /**
     * 筛选出需要固定显示的标签页
     */
    filterAffixTags(routes = [], basePath = '/') {
      let tags = []
      
      if (!routes || !routes.length) {
        return tags
      }
      
      routes.forEach(route => {
        if (route.meta && route.meta.affix) {
          const tagPath = this.pathResolve(basePath, route.path)
          tags.push({
            fullPath: tagPath,
            path: tagPath,
            name: route.name,
            meta: { ...route.meta }
          })
        }
        
        if (route.children && route.children.length) {
          const tempTags = this.filterAffixTags(route.children, route.path)
          if (tempTags.length >= 1) {
            tags = [...tags, ...tempTags]
          }
        }
      })
      return tags
    },
    
    /**
     * 路径解析辅助方法
     */
    pathResolve(basePath, routePath) {
      if (!routePath) return basePath
      if (routePath.startsWith('/')) return routePath
      return basePath === '/' ? `/${routePath}` : `${basePath}/${routePath}`
    },
    
    /**
     * 添加或更新当前路由到标签页
     */
    addViewTabs() {
      const { name, path, query, params, meta, fullPath } = this.$route
      const view = {
        name,
        path,
        query,
        params,
        meta,
        fullPath,
        title: meta?.title || 'no-name'
      }
      this.$store.dispatch('tagsView/addVisitedView', view)
    },
    
    /**
     * 处理标签点击事件
     */
    handleClick(tag) {
      if (this.$route.path === tag.path) {
        return
      }
      
      const { path, query, params } = tag
      this.$router.push({
        path,
        query,
        params
      }).catch(err => {
        if (err.name !== 'NavigationDuplicated') {
          throw err
        }
      })
    },
    
    /**
     * 关闭选中的标签
     */
    closeSelectedTag(view) {
      this.$store.dispatch('tagsView/delView', view).then(({ visitedViews }) => {
        if (this.isActive(view)) {
          this.toLastView(visitedViews, view)
        }
      })
    },
    
    /**
     * 跳转到最后一个标签
     */
    toLastView(visitedViews, view) {
      const latestView = visitedViews.slice(-1)[0]
      if (latestView) {
        if (this.$route.path !== latestView.path) {
          this.$router.push(latestView.path).catch(err => {
            if (err.name !== 'NavigationDuplicated') {
              throw err
            }
          })
        }
      } else {
        if (view.name === 'Dashboard') {
          if (this.$route.path !== '/redirect/dashboard') {
            this.$router.push('/redirect/dashboard').catch(err => {
              if (err.name !== 'NavigationDuplicated') {
                throw err
              }
            })
          }
        } else {
          if (this.$route.path !== '/') {
            this.$router.push('/').catch(err => {
              if (err.name !== 'NavigationDuplicated') {
                throw err
              }
            })
          }
        }
      }
    },
    
    /**
     * 处理下拉菜单命令
     */
    handleCommand(command) {
      if (command === 'closeOthers') {
        this.closeOthersTags()
      } else if (command === 'closeAll') {
        this.closeAllTags()
      }
    },
    
    /**
     * 关闭其他标签
     */
    closeOthersTags() {
      this.$store.dispatch('tagsView/delAllVisitedViews').then(() => {
        this.$store.dispatch('tagsView/addVisitedView', this.$route)
      })
    },
    
    /**
     * 关闭所有标签
     */
    closeAllTags() {
      this.$store.dispatch('tagsView/delAllVisitedViews').then(() => {
        if (this.$route.path !== '/') {
          this.$router.push('/').catch(err => {
            if (err.name !== 'NavigationDuplicated') {
              throw err
            }
          })
        }
      })
    }
  }
}
</script>

<style lang="scss" scoped>
.tabs-container {
  height: 42px;
  background-color: #fff;
  border-bottom: 1px solid #d8dce5;
  box-shadow: 0 1px 3px 0 rgba(0, 0, 0, .12), 0 0 3px 0 rgba(0, 0, 0, .04);
  display: flex;
  justify-content: space-between;
  align-items: center;
  position: relative;
  
  .scroll-container {
    white-space: nowrap;
    position: relative;
    overflow: hidden;
    width: calc(100% - 30px);
    height: 42px;
    
    .tabs-nav {
      padding: 0 15px;
      height: 42px;
      display: flex;
      align-items: center;
      
      .button-tab {
        cursor: pointer;
        margin-right: 10px;
        padding: 0 15px;
        height: 32px;
        line-height: 32px;
        background-color: #fff;
        color: #606266;
        font-size: 14px;
        border: 1px solid #dcdfe6;
        border-radius: 4px;
        display: flex;
        align-items: center;
        justify-content: center;
        position: relative;
        
        .el-icon-close {
          margin-left: 6px;
          font-size: 12px;
          width: 16px;
          height: 16px;
          vertical-align: middle;
          border-radius: 50%;
          text-align: center;
          line-height: 16px;
          
          &:hover {
            background-color: #f56c6c;
            color: #fff;
          }
        }
        
        &:hover {
          color: #409EFF;
          border-color: #c6e2ff;
          background-color: #ecf5ff;
        }
        
        &.active {
          color: #fff;
          background-color: #409EFF;
          border-color: #409EFF;
          
          .el-icon-close {
            &:hover {
              background-color: #fff;
              color: #f56c6c;
            }
          }
        }
      }
    }
  }
  
  .tabs-actions {
    width: auto;
    min-width: 30px;
    height: 100%;
    display: flex;
    justify-content: flex-end;
    align-items: center;
    padding-right: 10px;
    
    .tabs-action-button {
      margin-right: 20px;
      cursor: pointer;
      font-size: 18px;
      
      &:hover {
        color: #409EFF;
      }
    }
  }
  
  ::v-deep .el-scrollbar__wrap {
    height: 42px;
    overflow-x: auto;
    overflow-y: hidden;
    
    &::-webkit-scrollbar {
      display: none;
    }
  }
  
  ::v-deep .el-scrollbar__bar {
    &.is-horizontal {
      display: none;
    }
    
    &.is-vertical {
      display: none;
    }
  }
}
</style> 